home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Misc / aa_m68k_Only / NDCamera.0.21 / Source / MiscSources.subproj / MiscStringInsertion.m < prev    next >
Encoding:
Text File  |  1995-04-12  |  7.2 KB  |  278 lines

  1. //
  2. //    MiscStringInsertion.m
  3. //        Written by Don Yacktman Copyright (c) 1993 by Don Yacktman.
  4. //                Version 1.95  All rights reserved.
  5. //        This notice may not be removed from this source code.
  6. //
  7. //    This object is included in the MiscKit by permission from the author
  8. //    and its use is governed by the MiscKit license, found in the file
  9. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  10. //    for a list of all applicable permissions and restrictions.
  11. //    
  12.  
  13. #import <misckit/MiscString.h>
  14.  
  15. @implementation MiscString(Insertion)
  16.  
  17. // This category is composed of methods which insert characters or
  18. // strings into a MiscString.
  19.  
  20. - cat:(const char *)aString
  21. {
  22.     if (!aString) return nil; // so strlen() stays sane.  Thanks Steve Hayman!
  23.     return [self cat:aString n:strlen(aString) fromZone:[self zone]];
  24. }
  25.  
  26. - cat:(const char *)aString n:(int)n
  27. {
  28.     return [self cat:aString n:n fromZone:[self zone]];
  29. }
  30.  
  31. - cat:(const char *)aString fromZone:(NXZone *)zone
  32. {
  33.     if (!aString) return nil; // so strlen() stays sane.  Thanks Steve Hayman!
  34.     return [self cat:aString n:strlen(aString) fromZone:zone];
  35. }
  36.  
  37. - cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
  38. {
  39.     char *newBuffer; int newSize;
  40.     if (!(aString || buffer)) return nil;
  41.     if (!buffer) { // Not very efficient, but safer.
  42.         char *tempBuffer = (char *)NXZoneMalloc(zone, n+1);
  43.         if (!tempBuffer) return nil;
  44.         strncpy(tempBuffer, aString, n);
  45.         tempBuffer[n] = '\0';
  46.         [self setStringValue:tempBuffer fromZone:zone];
  47.         free(tempBuffer);
  48.         return self;
  49.     }
  50.     if (!aString) return self;
  51.     if (n > strlen(aString)) n = strlen(aString);
  52.     newSize = length + n + 1;
  53.     if (newSize > _length) {
  54.         newBuffer = (char *)NXZoneMalloc(zone, newSize);
  55.         _length = newSize;
  56.         newBuffer[0] = '\0';
  57.         strcat(newBuffer, buffer);
  58.         strncat(newBuffer, aString, n);
  59.         free(buffer);
  60.         buffer = newBuffer;
  61.     } else  strncat(buffer, aString, n);
  62.     length = strlen(buffer);
  63.     return self;
  64. }
  65.  
  66. - concatenate:sender
  67. { // note return self here; assume that there's nothing to add...
  68.     if (![sender respondsTo:@selector(stringValue)]) return self;
  69.     return [self cat:[sender stringValue]
  70.                  n:strlen([sender stringValue])
  71.                  fromZone:[self zone]];
  72. }
  73.  
  74. - concatenate:sender n:(int)n
  75. {
  76.     if (![sender respondsTo:@selector(stringValue)]) return self;
  77.     return [self cat:[sender stringValue] n:n fromZone:[self zone]];
  78. }
  79.  
  80. - concatenate:sender fromZone:(NXZone *)zone
  81. {
  82.     if (![sender respondsTo:@selector(stringValue)]) return self;
  83.     return [self cat:[sender stringValue]
  84.             n:strlen([sender stringValue]) fromZone:zone];
  85. }
  86.  
  87. - concatenate:sender n:(int)n fromZone:(NXZone *)zone
  88. {
  89.     if (![sender respondsTo:@selector(stringValue)]) return self;
  90.     return [self cat:[sender stringValue] n:n fromZone:zone];
  91. }
  92.  
  93. - insert:(const char *)aString at:(int)index
  94. // inserts given string into buffer starting at index.
  95. // (the first character is position #0)
  96. {
  97.     id temp1;
  98.     id temp2;
  99.  
  100.     if ((aString == NULL) || (strlen(aString)<=0)) return self;
  101.     if (index < 0) index = 0;         
  102.     if (index >= length) return [self cat:aString];
  103.  
  104.     temp1 = [self left:index];
  105.     if (!temp1) temp1 = [[[self class] alloc] init];
  106.     temp2 = [self right:length-index];  
  107.     [[temp1 cat:aString] concatenate:temp2];
  108.     [self setStringValue:[temp1 stringValue]];
  109.  
  110.     [temp1 free];
  111.     [temp2 free];
  112.     return self;
  113. }
  114.  
  115. - insertString:(id)sender at:(int)index
  116. // cover for insert:at: for a String object
  117. {
  118.     if (![sender respondsTo:@selector(stringValue)]) return self;
  119.     return [self insert:[sender stringValue] at:index];
  120. }
  121.  
  122. - insertChar:(char)aChar at:(int)index
  123. {
  124.     id tempStr;
  125.     id retval;
  126.  
  127.     if (aChar == 0) return self;    // or should this return nil? DAY: leave it
  128.  
  129.     tempStr = [[[[[self class] alloc] init] allocateBuffer:2] addChar:aChar];
  130.     retval = [self insert:[tempStr stringValue] at:index];
  131.     [tempStr free];
  132.     return retval;
  133. }
  134.  
  135. - insertChar:(char)aChar    // does an insert at the front (for chars)
  136. { // added for convenience; as you see it is redundant.
  137.     return [self insertChar:aChar at:0];
  138. }
  139.  
  140. // catStrings:    - a convenience function to append a list of strings
  141. //                to a string object.
  142. //    use like this:
  143. //        [aString addStrings:string0, string1, string2, string3, string4, NULL];
  144. //    make sure to have the ending NULL!
  145. //
  146. // Note from Don:  I've decided to use a version sent in by David Moffett
  147. //        since it is a bit more concise.
  148.  
  149. - catStrings:  ( const char *) strings,  ...;
  150. {
  151.     const char *aString;
  152.     va_list ptr;
  153.   
  154.     va_start( ptr, strings );
  155.     aString = strings;
  156.     while (aString) {
  157.         [self cat:aString n:strlen(aString) fromZone:[self zone]];
  158.         aString = va_arg(ptr, char *);
  159.     }
  160.     va_end( ptr );       
  161.     return self;
  162. }
  163.  
  164. // and here's one modified to handle MiscStrings -- don
  165. - concatenateStrings:(id)strings,  ...
  166. {
  167.     id aString;
  168.     va_list ptr;
  169.   
  170.     va_start(ptr, strings);
  171.     aString = strings;
  172.     while (aString) {
  173.         if ([aString respondsTo:@selector(stringValue)]) {
  174.             const char *sptr = [aString stringValue];
  175.             [self cat:sptr
  176.                     n:([aString respondsTo:@selector(length)] ?
  177.                             [aString length] : strlen(sptr))
  178.                     fromZone:[self zone]];
  179.         }
  180.         aString = va_arg(ptr, id);
  181.     }
  182.     va_end( ptr );       
  183.     return self;
  184. }
  185.  
  186. - insert:(const char *)aString    // does an insert at the front (for char *'s)
  187. { // added for convenience; as you see it is redundant.
  188.     return [self insert:aString at:0];
  189. }
  190.  
  191. - insertString:aString    // does an insert at the front (for objects)
  192. { // added for convenience; as you see it is redundant.
  193.     return [self insertString:aString at:0];
  194. }
  195.  
  196. - addChar:(char)aChar
  197. {
  198.   if (aChar) [self cat:&aChar n:1];
  199.   return self;
  200. }
  201.  
  202.  
  203. // The following methods are from the MOString by Mike Ferris:
  204.  
  205. - insertFromFormat:(const char *)format, ...
  206. // Prepends the given format string after formatting before the contents
  207. // of the receiver.
  208. {
  209.     va_list param_list;
  210.     
  211.     va_start(param_list, format);
  212.     [self insertAt:0 fromFormat:format, param_list];
  213.     va_end(param_list);
  214.     return self;
  215. }
  216.  
  217. - insertAt:(int)index fromFormat:(const char *)format, ...
  218. {
  219.     char *buf;
  220.     va_list param_list;
  221.     
  222.     va_start(param_list, format);
  223.     buf = MiscBuildStringFromFormatV(format, param_list);
  224.     [self insert:buf at:index];
  225.     NX_FREE(buf);
  226.     va_end(param_list);
  227.     return self;
  228. }
  229.  
  230. - catFromFormat:(const char *)format, ...
  231. // Appends to the string from the printf style format string and arguments.
  232. {
  233.     char *buf;
  234.     va_list param_list;
  235.  
  236.     va_start(param_list, format);
  237.     buf = MiscBuildStringFromFormatV(format, param_list);
  238.     [self cat:buf];
  239.     NX_FREE(buf);
  240.     va_end(param_list);
  241.     return self;
  242. }
  243.  
  244. // Here's an alternative way to catFromFormat, courtesy of Steve Hayman.
  245. // For now, we're keeping everything in the MiscBuildStringFromFormatV
  246. // function for simplicity.
  247. /* This method is currently commented out and not compiled.
  248. - printf:(const char *)fmt, ...
  249. {
  250.     NXStream *mem;
  251.     char *streambuf;
  252.     int len, maxlen;
  253.     va_list  ap;
  254.  
  255.     va_start(ap, fmt);
  256.     
  257.     // open a memory stream ...
  258.     mem = NXOpenMemory( NULL, 0, NX_WRITEONLY );
  259.     
  260.     // printf everything to the memory stream ...
  261.     NXVPrintf( mem, fmt, ap );
  262.     // and make sure it's null terminated
  263.     NXPutc( mem, '\0' );
  264.     // and get pointers to the buffer where the stream is ...
  265.     NXGetMemoryBuffer( mem, &streambuf, &len, &maxlen );
  266.     
  267.     // and append the text to ourself
  268.     [self cat:streambuf];
  269.     
  270.     // and free the memory stream.
  271.     NXCloseMemory(mem, NX_FREEBUFFER);
  272.     va_end(ap);
  273.  
  274.     return self;
  275. }
  276. */
  277. @end
  278.